{
 "cells": [
  {
   "cell_type": "code",
   "execution_count": 59,
   "metadata": {
    "collapsed": true,
    "pycharm": {
     "name": "#%%\n"
    }
   },
   "outputs": [
    {
     "data": {
      "text/plain": "<Figure size 432x288 with 1 Axes>",
      "image/png": "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\n"
     },
     "metadata": {
      "needs_background": "light"
     },
     "output_type": "display_data"
    },
    {
     "name": "stdout",
     "output_type": "stream",
     "text": [
      "torch.Size([10, 100])\n"
     ]
    }
   ],
   "source": [
    "from typing import List, Tuple\n",
    "from torch import Tensor\n",
    "import random\n",
    "import numpy as np\n",
    "import matplotlib.pyplot as plt\n",
    "from sklearn.decomposition import PCA\n",
    "from sklearn.manifold import TSNE\n",
    "import matplotlib.cbook as cbook\n",
    "\n",
    "\n",
    "def decompression_embedding(embedding: Tensor, algo: str = \"pca\") -> Tuple[List[float], List[float]]:\n",
    "    embedding_np: np.ndarray = embedding.detach().cpu().numpy()\n",
    "\n",
    "    if algo == 'pca':\n",
    "        decomposition = PCA(n_components=2)\n",
    "\n",
    "    elif algo == 'tsne':\n",
    "        decomposition = TSNE(n_components=2)\n",
    "    else:\n",
    "        raise ValueError(f'algo<{algo}> not supported ...')\n",
    "\n",
    "    de_embeddings: np.ndarray = decomposition.fit_transform(embedding_np)\n",
    "    return de_embeddings[:, 0], de_embeddings[:, 1]\n",
    "\n",
    "def gen_color_by_numbers(count: int) -> List[str]:\n",
    "    \"\"\"\n",
    "    gen colors by numbers\n",
    "    \"\"\"\n",
    "    colors: List[str] = []\n",
    "    for _ in range(count):\n",
    "        colors.append(\n",
    "            \"#\" + ''.join([random.choice('0123456789ABCDEF') for j in range(6)])\n",
    "        )\n",
    "    return colors\n",
    "\n",
    "def show_embeddings(embeddings: Tensor, labels: List[str], output_img: str = './embeddings.png', title=\"word embedding scatter map\"):\n",
    "    assert len(embeddings.shape) == 2\n",
    "    assert embeddings.shape[0] == len(labels)\n",
    "\n",
    "    x, y = decompression_embedding(embeddings, 'pca')\n",
    "\n",
    "    label_set = list(set(labels))\n",
    "    colors = gen_color_by_numbers(len(label_set))\n",
    "    embedding_color = []\n",
    "\n",
    "    for label in labels:\n",
    "        index = label_set.index(label)\n",
    "        embedding_color.append(colors[index])\n",
    "\n",
    "    fig, ax = plt.subplots()\n",
    "    for index, (point_x, point_y) in enumerate(zip(x, y)):\n",
    "        color = colors[label_set.index(labels[index])]\n",
    "        ax.scatter(point_x, point_y, c=color, label=labels[index])\n",
    "\n",
    "    ax.legend(loc='upper right')\n",
    "    ax.set_title(title)\n",
    "    fig.tight_layout()\n",
    "\n",
    "    plt.savefig(output_img)\n",
    "\n",
    "    plt.show()\n",
    "\n",
    "\n",
    "import torch\n",
    "\n",
    "words_n = 10\n",
    "embeddings = torch.randn(words_n, 100)\n",
    "\n",
    "show_embeddings(embeddings, [str(i) for i in range(words_n)])\n",
    "print(embeddings.shape)\n"
   ]
  }
 ],
 "metadata": {
  "kernelspec": {
   "name": "python388jvsc74a57bd0dac504a1b45ccde4581675a301266d1beca20c04c7113f5cd8e0d2a32f00ef0c",
   "language": "python",
   "display_name": "Python 3.8.8 64-bit ('torch': conda)"
  },
  "language_info": {
   "codemirror_mode": {
    "name": "ipython",
    "version": 2
   },
   "file_extension": ".py",
   "mimetype": "text/x-python",
   "name": "python",
   "nbconvert_exporter": "python",
   "pygments_lexer": "ipython2",
   "version": "2.7.6"
  }
 },
 "nbformat": 4,
 "nbformat_minor": 0
}